﻿using System;
using System.Drawing;

namespace SQLLink.DomainClasses
{
    public class Marker
    {
        public string     Name              { get; set; }               //The name of the marker
        public int        Id                { get; set; }               //The id of the marker
        public MarkerType Type              { get; set; }               //The type of the marker

        public LatLon     LatLon            { get; set; }               //The latlon object of the marker
        public MarkerSize Size              { get; set; }               //The size of the marker
        public Color      Color             { get; set; }               //The color of the marker
        public char       Label             { get; set; }               //The label of the marker
        public bool       HasPassed         { get; set; }               //The hasPassed property (used for busses only)

        public double DistanceFromDeparture  { get; private set; }      //The absolute distance from this marker from the departure
        public double DistanceToDestination  { get; private set; }      //The absolute distance from this marker to the destination
        public double DistanceToNearestBus   { get; set; }              //The absolute distance to the nearest bus

        public Marker NextMarker { get; set; } //The following marker of a bus
        public Marker PreviousMarker { get; set; } //The previous marker of a bus

        public bool Localized { get; set; }                             //Indicates if a latlon has been found for this marker

        /// <summary>
        /// Marker(string, int, MarkerType)
        /// This is a Marker object specific constructor
        /// It is used when the marker is created without knowing its latlon position
        /// </summary>
        /// <param name="iName">The name of the marker</param>
        /// <param name="iId">The id of the marker</param>
        /// <param name="iType">The type of the marker</param>
        public Marker(string iName, int iId, MarkerType iType)
        {
            //Searches google API to find a LatLon from the name of the marker
            LatLon = new LatLon(iName);
            Initialize(iName, iId, iType);
        }

        /// <summary>
        /// Marker(LatLon, string, int, MarkerType)
        /// This is a Marker object specific constructor
        /// It is used when the marker is created knowing its latlon position
        /// </summary>
        /// <param name="latlon">The known latlon of the marker</param>
        /// <param name="iName">The name of the marker</param>
        /// <param name="iId">The id of the marker</param>
        /// <param name="iType">The type of the marker</param>
        public Marker(LatLon latlon, string iName, int iId, MarkerType iType)
        {
            //Sets the latlon object
            LatLon = latlon;
            Initialize(iName, iId, iType);
        }

        /// <summary>
        /// SetType(MarkerType)
        /// This method changes the type of a marker
        /// </summary>
        /// <param name="iType">The type of the marker</param>
        public void SetType(MarkerType iType)
        {
            Initialize(Name, Id, iType);
        }

        /// <summary>
        /// ComputeDistanceToDestination(Marker)
        /// This method computes the distance to destination of the marker
        /// </summary>
        /// <param name="arrival">The marker to which we compute the distance</param>
        public void ComputeDistanceToDestination(Marker arrival)
        {
            DistanceToDestination = ComputeDistanceToMarker(arrival);
        }

        /// <summary>
        /// ComputeDistanceFromDeparture(Marker)
        /// This method computes the distance from departure of the marker
        /// </summary>
        /// <param name="departure">The marker to which we compute the distance</param>
        public void ComputeDistanceFromDeparture(Marker departure)
        {
            DistanceFromDeparture = ComputeDistanceToMarker(departure);
        }

        /// <summary>
        /// This method returns a string representing the marker
        /// </summary>
        /// <returns>string representing the marker</returns>
        public override string ToString()
        {
            return Name;
        }

        /// <summary>
        /// ComputeDistanceToMarker(Marker)
        /// This methods computes the distance from this to the the specified marker
        /// </summary>
        /// <param name="marker">The marker to which we compute the distance</param>
        /// <returns></returns>
        public double ComputeDistanceToMarker(Marker marker)
        {
            //Gets the important points
            var x1 = marker.LatLon.Latitude;
            var y1 = marker.LatLon.Longitude;
            var x2 = LatLon.Latitude;
            var y2 = LatLon.Longitude;

            //Pythagore
            return Math.Sqrt(Math.Abs(Math.Pow(y2 - y1, 2) - Math.Pow(x2 - x1, 2)));
        }

        /// <summary>
        /// Initialize(string, int, MarkerType)
        /// This method initializes a marker to with its proper attributes values
        /// </summary>
        /// <param name="iName">The name of the marker</param>
        /// <param name="iId">The id of the marker</param>
        /// <param name="iType">The type of the marker</param>
        protected void Initialize(string iName, int iId, MarkerType iType)
        {
            //Sets the attributes
            Name      = iName;
            Id        = iId;
            Type      = iType;
            HasPassed = false;

            // Sets the label, the color and the size of the marker according to its type
            switch (iType)
            {
                case MarkerType.arrival:
                    Label = 'A';
                    Color = Color.Red;
                    Size = MarkerSize.small;
                    break;
                case MarkerType.departure:
                    Label = 'D';
                    Color = Color.Green;
                    Size = MarkerSize.small;
                    break;
                case MarkerType.owner:
                    Label = 'O';
                    Color = Color.Yellow;
                    Size = MarkerSize.mid;
                    break;
                case MarkerType.bus:
                    Label = 'B';
                    Color = Color.Blue;
                    Size = MarkerSize.mid;
                    break;
                default: // default is MarkerType.other
                    Label = 'S';
                    Color = Color.Black;
                    Size = MarkerSize.tiny;
                    break;
            }

            //Checks if the latlon is not {0,0}
            SetLocalized();
        }

        /// <summary>
        /// SetLocalized()
        /// This method sets/resets the Localized attribute
        /// </summary>
        public void SetLocalized()
        {
            Localized = (LatLon.Latitude > 0 || LatLon.Latitude < 0)
                && (LatLon.Longitude > 0 || LatLon.Longitude < 0);
        }
    }

    //Enum describing marker type
    public enum MarkerType
    {
        none, //Defaut value : Should not be used
        other,
        departure,
        owner,
        arrival,
        bus
    };

    //Enum describing marker object sizes from google API
    public enum MarkerSize
    {
        none,   //Default value : Should not be used
        tiny,
        mid,
        small
    };
}
